package cn.ad.server.web.spring.service.biz;

import cn.ad.server.common.utils.BeanUtils;
import cn.ad.server.common.utils.StringUtil;
import cn.ad.server.web.spring.model.AdImpression;
import cn.ad.server.web.spring.model.AdNative;
import cn.ad.server.web.spring.model.Exchange;
import cn.ad.server.web.spring.model.adview.*;
import cn.ad.server.web.spring.service.actions.context.BidContext;
import cn.ad.server.biz.internal.AdService;
import cn.ad.server.biz.internal.IAdspaceService;
import cn.ad.server.domain.ad.*;
import cn.ad.server.domain.enumration.AdFormat;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author dongbin.yu
 * @from 2016-07-28
 * @since V1.0
 */
@Component
public class AdViewImpressionMatchService extends ImpressionMatchService {

	private static Logger LOGGER = LoggerFactory.getLogger(AdViewImpressionMatchService.class);

	@Autowired
	private AdService adService;

	@Resource
	private String serverAddress;

	@Autowired
	private IAdspaceService adSpaceService;

	@Autowired
	private TrackingService trackingService;

	// @Value("${bid.adView.ratio}")
	// private double ratio;

	@Override
	public Exchange getExchange() {
		return Exchange.ADVIEW;
	}

	@Override
	public Bid handler(AdImpression impression, BidContext bidContext) {

		// 取得现在的广告形式
		AdViewImpression adViewImpression = (AdViewImpression) impression;
		AdFormat adFormat = AdViewFormat.FORMAT_MAP.get(adViewImpression.getInstl());

		// 区别原生和非原生
		// 策略列表
		Set<Strategy> strategyList = null;
		AdTemplate adTemplate = null;
		boolean serverFilter = false;
		int platformId = 0;
		// long adSpaceId = 0;
		AdSpace localAdSpace = null;
		if (adFormat != AdFormat.AD_NATIVE) {
			strategyList = adService.fetchPlatformById(Integer.parseInt(Exchange.ADVIEW.getValue())).getStrategies();
		} else {
			serverFilter = true;
			PlatformAdspaceMap platformAdspaceMap = adService.fetchAdspaceByTagId(adViewImpression.getTagid(),
					Integer.parseInt(getExchange().getValue()));
			if (platformAdspaceMap != null) {
				localAdSpace = adSpaceService.findAdSpaceByID(platformAdspaceMap.getAdSpaceId());
				// adSpaceId = localAdSpace.getId();
				strategyList = new HashSet<>(localAdSpace.getStrategys());
				adTemplate = localAdSpace.getAdTemplate();
				platformId = platformAdspaceMap.getPlatformId();
				bidContext.setAdxType(platformId);
			} else {
				return null;
			}
		}

		if (strategyList == null)
			return null;
		bidContext.setImpId(adViewImpression.getId());
		bidContext.setBidFloor(
				new BigDecimal(adViewImpression.getBidfloor()).divide(new BigDecimal(10000)).doubleValue());
		bidContext.setPriceUnit(adViewImpression.getBidfloorcur());
		bidContext.setAdFormat(adFormat.getValue());
		bidContext.setAdxTagId(adViewImpression.getTagid());

		if (adFormat == AdFormat.AD_NATIVE && adTemplate == null)
			return null;
		Banner banner = adViewImpression.getBanner();

		int width = 0;
		int height = 0;

		if (banner != null) {
			bidContext.setAdspaceWidth(String.valueOf(banner.getW()));
			bidContext.setAdspaceHeight(String.valueOf(banner.getH()));
			if (banner.getPos() != 0) {
				bidContext.setScreenPosition(String.valueOf(banner.getPos()));
			}

			if (banner.getBattr() != null) {
				bidContext.setExcludeCreativeType(StringUtil.arrayToCommaDelimitedString(banner.getBattr()));
			}

			if (banner.getMimes() != null) {
				bidContext.setIncludeMimes(StringUtil.arrayToCommaDelimitedString(banner.getMimes()));
			}

			width = banner.getW();
			height = banner.getH();
		}

		return (Bid) strategyFilter(strategyList, bidContext, adTemplate, adViewImpression.getPnative(), width, height,
				serverFilter, platformId, localAdSpace);
		
	}

	/**
	 * 组合Bid数据
	 *
	 * @param entry
	 * @return
	 */
	@Override
	public Bid compositeBid(BidContext bidContext, Entry entry) {

		Bid bid = new Bid();
		double ratio = adService.getRatio(bidContext.getCampaignId());
		bid.setPrice(entry.getPrice().multiply(new BigDecimal(10000 * ratio)).intValue());
		bid.setPaymode(Bid.payMode.valueOf(entry.getFeeType()).ordinal());
		bid.setImpid(bidContext.getImpId());

		// 交互方式转换
		// TODO 后面做成枚举
		int interactionType = entry.getInteractionType();
		switch (interactionType) {
		case 0:
			bid.setAdct(Bid.clickAction.UNKNOWN.getValue());
			break;
		case 1:
			bid.setAdct(Bid.clickAction.OPEN_WEB_PAGE.getValue());
			break;
		case 2:
			bid.setAdct(Bid.clickAction.DOWNLOAD_APP.getValue());
			break;
		}

		bid.setAdid(String.valueOf(entry.getCampaignId()));
	
		bid.setAdi(BeanUtils.convertIosUrl(entry.getMaterialUrl(), bidContext.getOs()));
		bid.setAdw(entry.getWidth());
		bid.setAdh(entry.getHeight());

		if (entry.getTemplateId() > 0) {
			NativeResponse nativeResponse = new NativeResponse();
			// adView remove
			// nativeResponse.setImptrackers(compositeImpUrls(bidContext,
			// entry).get("0"));

			ResponseAsset.Link link = new ResponseAsset().new Link();
			// adView remove
			// link.setUrl(compositeClickUrl(bidContext, entry));

			if (StringUtils.hasText(entry.getClicksTracking())) {
				link.setClicktrackers(entry.getClicksTracking().split("\\|\\|\\|"));
			}

			nativeResponse.setLink(link);

			Set<AdMaterialGroup> adMaterialGroups = entry.getAdMaterialGroups();
			Map<String, List<AdMaterialGroup>> adMaterialGroupMap = new HashMap<>();
			for (AdMaterialGroup adMaterialGroup : adMaterialGroups) {
				String indexValue = adMaterialGroup.getAdTemplateSpec().getIndexValue();

				if (indexValue.contains("img") && indexValue.contains("image")) {
					if (adMaterialGroupMap.containsKey("img")) {
						adMaterialGroupMap.get("img").add(adMaterialGroup);
					} else {
						ArrayList<AdMaterialGroup> adMaterialGroupList = new ArrayList<>();
						adMaterialGroupList.add(adMaterialGroup);
						adMaterialGroupMap.put("img", adMaterialGroupList);
					}
				} else {
					if (adMaterialGroupMap.containsKey(indexValue)) {
						adMaterialGroupMap.get(indexValue).add(adMaterialGroup);
					} else {
						ArrayList<AdMaterialGroup> adMaterialGroupList = new ArrayList<>();
						adMaterialGroupList.add(adMaterialGroup);
						adMaterialGroupMap.put(indexValue, adMaterialGroupList);
					}
				}
			}
			ResponseAsset[] responseAssets = new ResponseAsset[entry.getAssets().length];

			for (int i = 0; i < entry.getAssets().length; i++) {

				RequestAsset requestAsset = entry.getAssets()[i];
				int id = requestAsset.getId();
				ResponseAsset responseAsset = new ResponseAsset();
				responseAsset.setId(id);
				responseAsset.setRequired(requestAsset.getRequired());
				if (requestAsset.getData() != null) {
					List<AdMaterialGroup> adMaterialGroupList = adMaterialGroupMap.get("data");
					ResponseAsset.Data data = responseAsset.new Data();
					if (!CollectionUtils.isEmpty(adMaterialGroupList)) {
						AdMaterialGroup adMaterialGroup = adMaterialGroupList.get(0);
						if (adMaterialGroup != null && adMaterialGroup.getAdMaterial() != null) {
							data.setValue(adMaterialGroup.getAdMaterial().getMaterialText());
							adMaterialGroupList.remove(0);
						}
					}
					responseAsset.setData(data);
				} else if (requestAsset.getTitle() != null) {
					List<AdMaterialGroup> adMaterialGroupList = adMaterialGroupMap.get("title");
					ResponseAsset.Title title = responseAsset.new Title();
					if (!CollectionUtils.isEmpty(adMaterialGroupList)) {
						AdMaterialGroup adMaterialGroup = adMaterialGroupList.get(0);
						if (adMaterialGroup != null && adMaterialGroup.getAdMaterial() != null) {
							title.setText(adMaterialGroup.getAdMaterial().getMaterialText());
							adMaterialGroupList.remove(0);
						}
					}
					responseAsset.setTitle(title);
				} else if (requestAsset.getImg() != null) {
					ResponseAsset.Image image = responseAsset.new Image();
					List<AdMaterialGroup> adMaterialGroupList = requestAsset.getImg().getType() == 1
							? adMaterialGroupMap.get("icon") : adMaterialGroupMap.get("img");
					if (!CollectionUtils.isEmpty(adMaterialGroupList)) {
						AdMaterialGroup adMaterialGroup = adMaterialGroupList.get(0);
						if (adMaterialGroup != null && adMaterialGroup.getAdMaterial() != null) {
							AdMaterial adMaterial = adMaterialGroup.getAdMaterial();
							image.setUrl(adMaterial.getMaterialUrl());
							AdSize adSize = adMaterial.getAdSize();
							if (adSize != null) {
								image.setW(adMaterial.getAdSize().getWidth());
								image.setH(adMaterial.getAdSize().getHeight());
							}
							adMaterialGroupList.remove(0);
						}
					}
					responseAsset.setImg(image);
				}
				responseAssets[i] = responseAsset;

			}

			nativeResponse.setAssets(responseAssets);

			bid.setNativeResponse(nativeResponse);

		}

		bid.setAdurl(compositeClickUrl(bidContext, entry));
		bid.setNurl(compositeImpUrls(bidContext, entry));
		bid.setWurl(compositeWinNoticeUrl(bidContext, entry));
		bid.setAdmt(entry.getAdFormat() == AdFormat.AD_NATIVE.getValue() ? AdType.NATIVE.getValue()
				: AdType.PICTURE.getValue());

		if (StringUtils.hasText(entry.getClicksTracking())) {
			bid.setCurl(entry.getClicksTracking().split("\\|\\|\\|"));
		}

		bid.setCid(entry.getAuditId());

		return bid;
	}

	@Override
	public void storeTemplateSpec(Entry entry, AdNative adNative) {
		entry.setAssets(((Native) adNative).getRequest().getAssets());
	}

	/**
	 * 组合印象数据
	 *
	 * @param bidContext
	 * @param entry
	 * @return
	 */
	protected Map<String, String[]> compositeImpUrls(BidContext bidContext, Entry entry) {
		String impUrl = trackingService.buildImpressionUrl("2", NumberUtils.toInt(bidContext.getChannel(), 2),
				entry.getPlatformId(), 0, bidContext.getStrategyId(), bidContext.getCreativeId(),
				bidContext.getMaterialId(), bidContext.getGuid(), bidContext.getOs());
		String[] impUrls = new String[1];

		if (StringUtils.hasText(entry.getImpressionTracking())) {

			String[] impressionTracking = entry.getImpressionTracking().split("\\|\\|\\|");
			impUrls = new String[impressionTracking.length + 1];
			for (int i = 0; i < impressionTracking.length; i++) {
				impUrls[i + 1] = impressionTracking[i];
			}
		}
		impUrls[0] = impUrl;
		
		Map<String, String[]> map = new HashMap<>();
		map.put("0", impUrls);
		return map;

	}

	/**
	 * 组合点击数据
	 *
	 * @param bidContext
	 * @return
	 */
	protected String compositeClickUrl(BidContext bidContext, Entry entry) {
		String targetUrl = null;
		if (StringUtils.hasText(entry.getTargetUrl())) {
			try {
				targetUrl = URLEncoder
						.encode(convertTargetUrlHandler.getConvertTarget(bidContext, entry.getTargetUrl()), "UTF-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.warn("target url 转码失败.", e);
			}
		}
		// 添加扩展url
		String extend = convertTargetUrlHandler.convertExtendClickUrl(bidContext);

		return trackingService.buildClickUrl2(null, NumberUtils.toInt(bidContext.getChannel(), 2),
				entry.getPlatformId(), entry.getAdSpaceId(), bidContext.getStrategyId(), bidContext.getCreativeId(),
				bidContext.getMaterialId(), bidContext.getGuid(), targetUrl, extend, bidContext.getOs());

	}

	/**
	 * 组合赢价数据
	 *
	 * @param bidContext
	 * @return
	 */
	protected String compositeWinNoticeUrl(BidContext bidContext, Entry entry) {
		String impUrl = trackingService.buildWinoticeUrl("2", NumberUtils.toInt(bidContext.getChannel(), 2),
				entry.getPlatformId(), entry.getAdSpaceId(), bidContext.getStrategyId(), bidContext.getCreativeId(),
				bidContext.getMaterialId(), bidContext.getGuid(), bidContext.getOs());
		return (new StringBuilder(impUrl)).append("&win_price=%%WIN_PRICE%%").toString();
	}
	
	
	
}
